import { _decorator, Component, Node, EventTouch, Vec2, Vec3 , Label, Widget } from 'cc';
import { EventManager } from '../core/EventManager';
import { BilliardGame } from '../game/BilliardGame';
import { SoundManager } from '../framework/SoundManager';
import { Databus } from '../core/Databus';
import { WatchViewType } from '../core/CommUtil';
import DataEventReport from '../platform/DataEventReport';

const { ccclass, property } = _decorator;
const databus = Databus.Instance();
@ccclass('UserOperateController')
export class UserOperateController extends Component {
  private static MaxForceOffsetY = 350;
  private static MaxBiaoChiOffsetY = 360;
  // 方向面板控制参数
  private touchDirectionControl: Node = null;  // 微调触摸
  private directionBiaoChiOne: Node = null;
  private directionBiaoChiTwo: Node = null;
  private biaoTouchYPos =  0;
  // 力度控制参数
  private touchForceBoard: Node = null;   // 触摸力度
  private touchForceGan: Node = null;   // 触摸力度
  private forceTouchStartPos: Vec2 = null; // 力度触摸的起点位置
  private forcePercentNode: Node = null;
  private forcePercentText: Label = null;
  // 视角切换
  private switchViewer2D: Node = null;
  private switchViewer3D: Node = null;
  onLoad() {
    this.touchDirectionControl = this.node.getChildByName('DirectionControl');
    this.touchForceBoard = this.node.getChildByName('ForceControl');
    
    this.forcePercentNode = this.node.getChildByName('ForceControl').getChildByName('ForcePercentText');
    this.forcePercentText = this.forcePercentNode.getComponent(Label);
    this.directionBiaoChiOne = this.touchDirectionControl.getChildByName('BiaoChi').getChildByName('DirectionBiaoChiOne');
    this.directionBiaoChiTwo = this.touchDirectionControl.getChildByName('BiaoChi').getChildByName('DirectionBiaoChiTwo');
    
    this.directionBiaoChiOne.setPosition(new Vec3(
      this.directionBiaoChiOne.position.x, -UserOperateController.MaxBiaoChiOffsetY / 2, this.directionBiaoChiOne.position.z,
    ));

    this.directionBiaoChiTwo.setPosition(new Vec3(
      this.directionBiaoChiTwo.position.x, UserOperateController.MaxBiaoChiOffsetY / 2, this.directionBiaoChiTwo.position.z,
    ));

    this.biaoTouchYPos =  0;
    this.touchForceGan = this.touchForceBoard.getChildByName('ForceQiuGan').getChildByName('ForceGan');

    this.switchViewer2D = this.node.getChildByName('SwitchPerspectives').getChildByName('SwitchView2D');
    this.switchViewer3D = this.node.getChildByName('SwitchPerspectives').getChildByName('SwitchView3D');
    this.onEnableEvent();

    this.forcePercentNode.active = false;
    this.aliginMargin();

    
    this.switchViewer3D.active = true;
    this.switchViewer2D.active = false;
    if (BilliardGame.Instance().watchViewType === WatchViewType.View3D) {
      this.switchViewer3D.active = false;
      this.switchViewer2D.active = true;
    }
  }

  aliginMargin() {
    const tfWidget = this.touchForceBoard.getComponent(Widget);
    tfWidget.left = databus.sceenSize.alignMargin();
    const tdcWidget = this.touchDirectionControl.getComponent(Widget);
    tdcWidget.right = databus.sceenSize.alignMargin();
    const swhWidget = this.node.getChildByName('SwitchPerspectives').getComponent(Widget);
    swhWidget.left = databus.sceenSize.alignMargin() - 5;
  }
  update(deltaTime: number) {
    
  }

  onEnableEvent() {
    this.touchDirectionControl.on(Node.EventType.TOUCH_START, this.onDirectionStart, this);
    this.touchDirectionControl.on(Node.EventType.TOUCH_MOVE, this.onDirectionMove, this);
    this.touchDirectionControl.on(Node.EventType.TOUCH_END, this.onDirectionEnd, this);

    this.touchForceBoard.on(Node.EventType.TOUCH_START, this.onForceStart, this);
    this.touchForceBoard.on(Node.EventType.TOUCH_MOVE, this.onForceMove, this);
    this.touchForceBoard.on(Node.EventType.TOUCH_END, this.onForceEnd, this);
    this.touchForceBoard.on(Node.EventType.TOUCH_CANCEL, this.onForceEnd, this);

    this.switchViewer2D.on(Node.EventType.TOUCH_END, this.onViewSwith, this);
    this.switchViewer3D.on(Node.EventType.TOUCH_END, this.onViewSwith, this);
  }
  onDirectionStart(e: EventTouch) {
    const loc: Vec2 = e.getUILocation();
    this.biaoTouchYPos = loc.y;
  }
  onDirectionMove(e: EventTouch) {
    const loc: Vec2 = e.getUILocation();
    
    const delta = 1 * Math.floor((loc.y - this.biaoTouchYPos) / 5);
    this.directionBiaoChiOne.setPosition(new Vec3(this.directionBiaoChiOne.position.x, this.directionBiaoChiOne.position.y + delta, this.directionBiaoChiOne.position.z));
    this.directionBiaoChiTwo.setPosition(new Vec3(this.directionBiaoChiTwo.position.x, this.directionBiaoChiTwo.position.y + delta, this.directionBiaoChiTwo.position.z));
    const fact = BilliardGame.Instance().calculateDirectionFactor();
    EventManager.Instance().Emit("QiuGanDirectionChanged", delta * fact);
    if (this.directionBiaoChiOne.position.y > UserOperateController.MaxBiaoChiOffsetY) {
      this.directionBiaoChiOne.setPosition(
        this.directionBiaoChiOne.position.x,
        -UserOperateController.MaxBiaoChiOffsetY,
        this.directionBiaoChiOne.position.z,
      );
    }

    if (this.directionBiaoChiOne.position.y < -UserOperateController.MaxBiaoChiOffsetY) {
      this.directionBiaoChiOne.setPosition(
        this.directionBiaoChiOne.position.x,
        UserOperateController.MaxBiaoChiOffsetY,
        this.directionBiaoChiOne.position.z,
      );
    }

    if (this.directionBiaoChiTwo.position.y > UserOperateController.MaxBiaoChiOffsetY) {
      this.directionBiaoChiTwo.setPosition(
        this.directionBiaoChiTwo.position.x,
        -UserOperateController.MaxBiaoChiOffsetY,
        this.directionBiaoChiTwo.position.z,
      );
    }

    if (this.directionBiaoChiTwo.position.y < -UserOperateController.MaxBiaoChiOffsetY) {
      this.directionBiaoChiTwo.setPosition(
        this.directionBiaoChiTwo.position.x,
        UserOperateController.MaxBiaoChiOffsetY,
        this.directionBiaoChiTwo.position.z,
      );
    }

    SoundManager.Instance().playBiaoChiMove(0.5);

    this.biaoTouchYPos = loc.y;
  }
  onDirectionEnd(e: EventTouch) {
    SoundManager.Instance().stopBiaoChiMove();
  }

  onForceStart(e: EventTouch) {
    this.forcePercentNode.active = true;
    const loc: Vec2 = e.getUILocation();
    this.forceTouchStartPos = new Vec2(loc.x, loc.y);
    const percent = this.calcuForcePercent(loc.y);
    this.forcePercentText.string = `${Math.round(percent * 100)}`;
  }

  onForceMove(e: EventTouch) {
    const loc: Vec2 = e.getUILocation();
    const percent = this.calcuForcePercent(loc.y);
    // 最大移动区间是 [0, 300];
    const offsety: number = UserOperateController.MaxForceOffsetY * percent;

    // 设置控制力度杆往下移动
    this.touchForceGan.setPosition(new Vec3(0, -offsety, 0));
    this.forcePercentText.string = `${Math.round(percent * 100)}`;
    EventManager.Instance().Emit("QiuGanForceChanged", percent);
  }
  onForceEnd(e: EventTouch) {
    const loc: Vec2 = e.getUILocation();
    const percent = this.calcuForcePercent(loc.y);
    
    // 设置控制力度杆往下移动
    this.touchForceGan.setPosition(new Vec3(0, 0, 0));
    this.forcePercentText.string = `${Math.round(percent * 100)}`;

    if (percent <= 0) {
      // 回退到初始状态，可以重新选择球，然后调整方向
      BilliardGame.Instance().actionStage.initStage();
      return; // 相当于取消
    }
    if (BilliardGame.Instance().actionStage.canForceHit()) {
      this.forcePercentNode.active = false;
      EventManager.Instance().Emit("QiuGanForceEnded", percent);
    }
  }

  onViewSwith(e: EventTouch) {
    if (BilliardGame.Instance().watchViewType === WatchViewType.View3D) {
      this.switchViewer3D.active = true;
      this.switchViewer2D.active = false;
    } else {
      this.switchViewer3D.active = false;
      this.switchViewer2D.active = true;
    }
    BilliardGame.Instance().watchViewType = 1 - BilliardGame.Instance().watchViewType;
    EventManager.Instance().Emit("CameraRestart3DView", {});

    DataEventReport.Instance().reportComponentEvent(
      databus.sceneStack.currentPageName(), `SwitchView_${BilliardGame.Instance().watchViewType}`
    );
  }

  private calcuForcePercent(locy: number) {
    if (locy > this.forceTouchStartPos.y) return 0;
    const offsetTouch = Math.abs(locy - this.forceTouchStartPos.y);
    // 最大移动区间是 [0, MaxForceOffsetY];
    const offsety: number = Math.max(Math.min(UserOperateController.MaxForceOffsetY, offsetTouch), 0);
    const percent = offsety / UserOperateController.MaxForceOffsetY;
    return percent;
  }
}

